
parameter int NUM_PAGE_TYPS = 7,
              WID_SMEM_PAR  = n2w(NUM_SMEM_PAR),
              WID_DCHE_ASO  = n2w(NUM_DCHE_ASO),
              WID_DCHE_IDX  = n2w(NUM_DCHE_ENT),
              WID_DCHE_CL   = n2w(NUM_DCHE_CL),
              WID_SMEM_BK   = n2w(NUM_SMEM_BK),
              WID_ASID      = 8,
              WID_PGMSK     = 16,
              WID_PAR_OS    = WID_WORD + WID_SMEM_BK + WID_DCHE_CL + WID_DCHE_IDX + WID_SMEM_PAR,
              WID_IDX_OS    = WID_WORD + WID_SMEM_BK + WID_DCHE_CL + WID_DCHE_IDX,
              WID_NVADR     = 13,  /// 8K 13BIT START for tlb and dse, max2(13, WID_IDX_OS)
              WID_PFN       = 26,
              WID_PADR      = WID_NVADR + WID_PFN,    ///36
              WID_PFNB      = WID_PFN - WID_PGMSK,
              WID_LSV_RBUF  = n2w(NUM_LSV_RBUF),
              WID_LSV_SBUF  = n2w(NUM_LSV_SBUF),
              WID_LSV_LTB0  = n2w(NUM_LSV_LTB0),
              WID_LSV_STB0  = n2w(NUM_LSV_STB0),
              WID_LSV_LTB1  = n2w(NUM_LSV_LTB1),
              WID_LSV_STB1  = n2w(NUM_LSV_STB1),
              WID_LSV_STB2  = n2w(NUM_LSV_STB2);
              
parameter word CFG_START_ADR  = 'hf000_0000,
               VADR_MAPPED    = 'hF000_0000,
               VADR_NMAPNC    = 'hF7F0_0000,
               VADR_EJTAGS    = 'hF800_0000,
               VADR_NMAPCH    = 'h0000_0000,
               SMEM_OFFSET    = 'h00_0000,
               TFIF_OFFSET    = 'h20_0000,
               CTLR_OFFSET    = 'h24_0000,
               EJTG_OFFSET    = 'h24_1000,
               EBUS_OFFSET    = 'h24_2000;
               
parameter int SPAR_SIZE = NUM_SP * NUM_SMEM_PAR_W * 4,
              SMEM_SIZE = SPAR_SIZE * NUM_SMEM_PAR,
              MSGE_SIZE = 256, /// 256BYTE
              CTLR_SIZE = 128, /// each control register of pb 128byte
              EJTG_SIZE = 128; /// each ejtag of pb 128byte

parameter int NUM_ASB_CYC = max2(NUM_VEC / NUM_SMEM_BK, 1),
              WID_ASB_CYC = n2w(NUM_ASB_CYC);
typedef logic[WID_ASB_CYC-1:0] asbc_t;
typedef logic[WID_ASB_CYC:0] asbc2_t;

typedef logic[WID_SMEM_PAR - 1:0] par_t;
typedef logic[WID_DCHE_ASO - 1:0] aso_t;
typedef logic[WID_DCHE_IDX - 1:0] idx_t;
typedef logic[WID_DCHE_CL - 1:0] cl_t;
typedef logic[WID_SMEM_BK - 1:0] bk_t;
typedef logic[WID_WORD - 1:0] os_t;
typedef logic[WID_LSV_RBUF-1:0] lsid_t;
typedef logic[WID_LSV_RBUF-2:0] lsbid_t;
typedef logic[WID_LSV_SBUF-1:0] lssid_t;

typedef logic[WID_LSV_LTB0-1:0] ltbid0_t;
typedef logic[WID_LSV_STB0-1:0] stbid0_t;
typedef logic[WID_LSV_LTB1-1:0] ltbid1_t;
typedef logic[WID_LSV_STB1-1:0] stbid1_t;
typedef logic[WID_LSV_STB2-1:0] stbid2_t;

typedef enum logic[2:0] {
  rs_no,     rs_as_rdy,   rs_as,
  rs_w_sreq, rs_w_wb
} lsu_req_st_e;

typedef enum logic[2:0] {
  exr_ok,     exr_exok,     exr_err,    exr_tlb,
  exr_prot,   exr_ecc
} lsu_exrsp_e;

typedef enum logic[1:0] {
  rr_inv,   rr_ok,    rr_np,    rr_err
} lsu_rrsp_e;

typedef enum logic[2:0] {
  page_min   = 0,
  page_8x    = 1,
  page_64x   = 2,
  page_512x  = 3,
  page_2mx   = 4,
  page_8mx   = 5,
  page_max   = 6
} page_typ_e;

parameter int even_odd_bit_table[NUM_PAGE_TYPS] = '{
  0,
  3,
  6,
  9,
  11,
  13,
  15
};

typedef logic[WID_PGMSK - 1:0] pageMsk_t;

parameter pageMsk_t page_mask_table[NUM_PAGE_TYPS] = '{
  'b0000000000000000,   /// 8K
  'b0000000000000111,   /// 64K
  'b0000000000111111,   /// 512k
  'b0000000111111111,   /// 4M
  'b0000011111111111,   /// 16M
  'b0001111111111111,   /// 64M
  'b0111111111111111    /// 256M
};

typedef struct packed unsigned{
  par_t par;
  aso_t aso;
  idx_t idx;
  cl_t cl;
} smadr_t;

typedef struct packed unsigned{
  bk_t bk;
  os_t os;
} lwadr_t;

typedef struct packed unsigned{
  par_t par;
  aso_t aso;
  idx_t idx;
  cl_t cl;
  bk_t bk;
  os_t os;
} smfadr_t;

typedef struct packed unsigned{
  logic[WORD_BITS - WID_NVADR - WID_PGMSK - 1:0] v2;
  pageMsk_t msk;
} vpn_t;

typedef struct packed {
  logic [WID_PFNB - 1:0] b;
  pageMsk_t a; 
} pfn_t;

typedef struct packed unsigned{
  logic[WID_PADR - WID_PAR_OS - 1:0] tag;
  par_t par;
} tag_t;

///typedef struct packed unsigned{
///  tag_t t;
///  idx_t idx;
//////  cl_t cl;
///} exadr_ch_t;

///typedef struct packed unsigned{
//////  logic[$bits(exadr_ch_t) - $bits(smadr_t) - 1:0] d;
///  par_t par;
///  aso_t aso;
///  idx_t idx;
///} exadr_sm_t;

///typedef logic[WID_PADR - WID_WORD - WID_DCHE_CL - WID_SMEM_BK - 1:0] exadr_t;

typedef struct packed unsigned{
  tag_t t;
  idx_t idx;
  cl_t cl;
  bk_t bk;
  os_t os;
} padr_t;

typedef struct packed unsigned{
  logic [WORD_BITS - WID_PAR_OS - 1:0] ua;
  par_t par;
  idx_t idx;
  cl_t cl;
  bk_t bk;
  os_t os;
} vadr_t;

typedef struct packed unsigned{
  vpn_t vpn;
  logic [WID_NVADR - 1:0] nvadr;
} vadr2_t;

typedef struct{
  word[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0] data;
  logic[NUM_ASB_CYC-1:0] dv;
  lssid_t id;
} lsu_sd_inf_s;

parameter lsu_sd_inf_s lsu_sd_inf_def = '{
  default   : '0
};

typedef struct{
  logic ls, sm, lg, llsc;
  logic[1:0] ch, prot;
  smadr_t[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0] adr;
  logic [NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0][WORD_BYTES-1:0] v;
  lssid_t rid;
  tid_t tid;
  vadr_t chadr;
  grpid_t gid;
} lsu_ar_inf_s;

parameter lsu_ar_inf_s lsu_ar_inf_def = '{
  default   : '0
};

typedef struct packed{
  logic ld, s;
} lsu2dcu_rsp_s;

typedef struct packed{
  logic a, sd;
} lsu2dcu_req_s;

typedef struct{
  lsu2dcu_rsp_s rsp;
  lsu2dcu_req_s req;
  
  lsu_ar_inf_s ar;
  lsu_sd_inf_s sd;
} lsu2dcu_s;

parameter lsu2dcu_s lsu2dcu_def = '{
  ar        : lsu_ar_inf_def,
  sd        : lsu_sd_inf_def,
  default   : '0
};

typedef struct packed{
  logic a, sd;
} dcu2lsu_rsp_s;

typedef struct packed{
  logic ld, s;
} dcu2lsu_req_s;

typedef struct{
  byt[MCV-1:0][NUM_SP-1:0][WORD_BYTES-1:0] data;
  lssid_t id;
  lsu_exrsp_e[MCV-1:0][NUM_SP-1:0] exp;
} lsu_ld_inf_s;

parameter lsu_ld_inf_s lsu_ld_inf_def = '{
  exp       : '{default : exr_ok},
  default   : '0
};

typedef struct{
  lsu_exrsp_e[MCV-1:0][NUM_SP-1:0] exp;
  lssid_t id;
} lsu_s_inf_s;

parameter lsu_s_inf_s lsu_s_inf_def = '{
  exp       : '{default : exr_ok},
  default   : '0
};

typedef struct{
  dcu2lsu_rsp_s rsp;
  dcu2lsu_req_s req;
  
  lsu_ld_inf_s ld;
  lsu_s_inf_s s;
} dcu2lsu_s;

parameter dcu2lsu_s dcu2lsu_def = '{
  ld        : lsu_ld_inf_def,
  s         : lsu_s_inf_def,
  default   : '0
};

typedef struct{
  logic req;
} dpu2lsu_s;

parameter dpu2lsu_s dpu2lsu_def = '{
  default   : '0
};

typedef struct{
  imm_t imm;
  word d[NUM_SP], b[NUM_SP];
  logic v[NUM_SP];
} rfu2lsu_s;

parameter rfu2lsu_s rfu2lsu_def = '{
  d         : '{default : '0},
  b         : '{default : '0},
  v         : '{default : '0},
  default   : '0
};

typedef struct{
  irf_adr_t adr;
  logic crfw;
  logic v[MCV][NUM_SP];
  word data[MCV][NUM_SP];
  logic[MCV-1:0][NUM_SP-1:0] flag;
} lsu2rfu_s;

parameter lsu2rfu_s lsu2rfu_def = '{
  v         : '{default : '0},
  data      : '{default : '0},
  default   : '0
};

typedef struct{
  lsu_req_st_e st;
  isu_rf_adr_s wrf;
  ltid_t ltid;
  lid_t lid;
  logic ls, lg, asyn;
  logic[1:0] ch, prot;
  logic[3:0] fun;
  grpid_t gid;
  logic[MCV-1:0] vas;
  logic[MCV-1:0][NUM_SP-1:0] v;
  lsu_rrsp_e[MCV-1:0][NUM_SP-1:0] rr;
  isu_oid_t oid;
  lssid_t srcnt;
} lsu_req_inf_s;

parameter lsu_req_inf_s lsu_req_inf_def = '{
  wrf       : isu_rf_adr_def,
  st        : rs_no,
  rr        : '{default : rr_err},
  default   : '0
};

typedef struct{
  logic[MCV-1:0] vds;
  lsbid_t rid;
  logic rlid, v;
  logic[NUM_ASB_CYC-1:0] dv;
} lsu_sreq_inf_s;

parameter lsu_sreq_inf_s lsu_sreq_inf_def = '{
  default   : '0
};

typedef struct packed unsigned {
  word adr;
} lsu_adr_inf_s;

typedef struct packed unsigned {
  cyc_t c;
  spid_t s;
  os_t o;
} lsu_sel_inf_s;

typedef struct packed unsigned{
  asbc_t c;
  logic v;
} lsu_asbc_inf_s;

typedef struct packed unsigned {
  logic[WORD_BYTES-1:0] bv;
  smadr_t adr;
} lsu_exa_inf_s;

typedef struct packed unsigned {
  lsu_exa_inf_s[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0] exa;
  vadr_t adr;
  logic sm;
} lsu_exa_buf_s;

typedef struct{
  smfadr_t adr;
  logic v, m, mb;
  spid_t mid;
  asbc_t c;
} lsu_ads2_inf_s;

parameter lsu_ads2_inf_s lsu_ads2_inf_def = '{
  default   : '0
};

typedef struct{
  logic v;
  asbc_t c;
} lsu_ads3_inf_s;

parameter lsu_ads3_inf_s lsu_ads3_inf_def = '{
  default   : '0
};

typedef struct{
  logic v, start, kp, wb, llsc, ls;
  cyc_t cyc;
  lsbid_t rid;
  lssid_t sid;
  logic[WID_SMTLB_TGRP-1:0] tlbId;
  logic sm;
} lsu_ads_pip_inf_s;

parameter lsu_ads_pip_inf_s lsu_ads_pip_inf_def = '{
  default   : '0
};

typedef struct{
  logic v, start, wb, ls, rlid;
  cyc_t cyc;
  lsbid_t rid;
  lssid_t sid;
  logic[3:0] fun;
} lsu_das_pip_inf_s;

parameter lsu_das_pip_inf_s lsu_das_pip_inf_def = '{
  default   : '0
};

typedef struct{
  lsbid_t bcnt[2], es;
  lsu_sel_inf_s[NUM_VEC-1:0][WORD_BYTES-1:0] sel[2];
  logic ls;
  cyc_t cyc;
  lssid_t sldcnt, sstcnt;
  
  ///temp buffers
  logic ltb0f, ltb1f, stb0f, stb1f, stb2f, 
        ltb0rf, stb0rf, stb1rf;
  stbid0_t stb0rp, stb0wp, stb0rdy, stb0ds;
  ltbid0_t ltb0rp, ltb0wp, ltb0rdy;
  ltbid1_t ltb1rp, ltb1wp;
  stbid1_t stb1rp, stb1wp, stb1rdy, stb01dif;
  stbid2_t stb2rp, stb2wp;
  lssid_t stb0[NUM_LSV_STB0], ltb0[NUM_LSV_LTB0];
  lsu_s_inf_s stb2[NUM_LSV_STB2], ltb1[NUM_LSV_LTB1];
  lssid_t stb1[NUM_LSV_STB1];
  
  lsu_exrsp_e[MCV-1:0][NUM_SP-1:0] dsExp[3];
  lsu_exrsp_e[MCV-1:0][NUM_SP-1:0] dsExpRd;
  
  lsu_sel_inf_s[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0][WORD_BYTES-1:0] asb[2];
  lsu_asbc_inf_s[MCV-1:0][NUM_SP-1:0] asbc[2];
  asbc2_t ascnt[2][NUM_SMEM_BK];
  lsu_exa_inf_s[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0] exa[2];
  logic[NUM_ASB_CYC-1:0][NUM_SMEM_BK-1:0] exav[2];
  lsu_ads_pip_inf_s asp[3][2];
  vadr_t as2adr[2];
  lsu_ads2_inf_s as2[2][NUM_SP];
  lsu_ads3_inf_s as3[2][NUM_SP];
  logic[MCV-1:0] vas[2];

  lsu_das_pip_inf_s dsp[2][3];
  byt[MCV-1:0][NUM_SP-1:0][WORD_BYTES-1:0] resb[2];
  lsu_rrsp_e[NUM_VEC-1:0] resr[3];
  logic[MCV-1:0] vsds[2], vsas[2];
  
  word[MCV-1:0][NUM_SP-1:0] rfsdb;
  
  lsu2isu_s lsu2isu;
  ///handshake is one cycle ahead for dcu sd a req
  logic startDCUsdReq, stallDCUsdReq, dcuSdReq,
                       stallDCUaReq,  dcuAReq,
        startFinalReq, stallFinalReq, finalReq;
  logic frLid, aExLs;
  lsbid_t frId;
  lssid_t sdExId, aExId;
  logic[WID_LSV_STB0:0] eaRadr;
} lsu_inf_s;

parameter lsu_inf_s lsu_inf_def = '{
  bcnt      : '{default : '0},
  sel       : '{default : '0},
  asb       : '{default : '0},
  asbc      : '{default : '0},
  ascnt     : '{default : '0},
  exa       : '{default : '0},
  exav      : '{default : '0},
///  asw       : '{default : '0},
  asp       : '{default : lsu_ads_pip_inf_def},
  as2adr    : '{default : '0},
  as2       : '{default : lsu_ads2_inf_def},
  as3       : '{default : lsu_ads3_inf_def},
  dsp       : '{default : lsu_das_pip_inf_def},
  resb      : '{default : '0},
  resr      : '{default : rr_err},
  vas       : '{default : '0},
  vsds      : '{default : '0},
  vsas      : '{default : '0},
  ltb0      : '{default : '0},
  stb0      : '{default : '0},
  stb2      : '{default : lsu_s_inf_def},
  ltb1      : '{default : lsu_s_inf_def},
  dsExp     : '{default : exr_ok},
  lsu2isu   : lsu2isu_def,
  default   : '0
};

typedef struct{
  word[MCV-1:0][NUM_SP-1:0] rfwbb;
  lsu2dcu_s lsu2dcu;
  lsu2rfu_s lsu2rfu;
  word rfuLD[MCV][NUM_SP];
  word[MCV-1:0][NUM_SP-1:0] dcuSD;
  lsu_sel_inf_s[NUM_VEC-1:0][WORD_BYTES-1:0] ssDatao[2];
  lsu_asbc_inf_s[NUM_VEC-1:0]scDatao[3];
  lwadr_t[NUM_VEC-1:0] saDatao[3];
  lsu_adr_inf_s[NUM_SP-1:0] aDatao[2];
  byt[MCV-1:0][NUM_SP-1:0][WORD_BYTES-1:0] srcb[2];
  isu2lsu_s isu[3];
  rfu2lsu_s rfu;
  dcu2lsu_s dcu;
} lsu_io_inf_s;

parameter lsu_io_inf_s lsu_io_inf_def = '{
  lsu2dcu   : lsu2dcu_def,
  lsu2rfu   : lsu2rfu_def,
  aDatao    : '{default : '0},
  ssDatao   : '{default : '0},
  scDatao   : '{default : '0},
  saDatao   : '{default : '0},
  srcb      : '{default : '0},
  rfuLD     : '{default : '0},
  isu       : '{default : isu2lsu_def},
  rfu       : rfu2lsu_def,
  dcu       : dcu2lsu_def,
  default   : '0
};